Skip to content

feat(skill-manager): prevent removed external skills from being redis…#1242

Open
gastoner wants to merge 1 commit intokortex-hub:mainfrom
gastoner:skill_removal_enhancement
Open

feat(skill-manager): prevent removed external skills from being redis…#1242
gastoner wants to merge 1 commit intokortex-hub:mainfrom
gastoner:skill_removal_enhancement

Conversation

@gastoner
Copy link
Copy Markdown
Contributor

@gastoner gastoner commented Apr 4, 2026

…covered on re-init

Adds a SKILL_REMOVED config key and a removedNames set to SkillManager. When an external (non-managed) skill is unregistered, its name is stored in skills.removed and persisted to config. Discovery skips any skill whose name appears in that set, preventing it from reappearing after a restart or folder re-registration.

Also narrows isManagedSkill to only check the Kortex skills directory (not all registered folders), so extension-registered skills are always treated as external and correctly tracked as removed rather than deleted.

…covered on re-init

Adds a `SKILL_REMOVED` config key and a `removedNames` set to SkillManager.
When an external (non-managed) skill is unregistered, its name is stored in
`skills.removed` and persisted to config. Discovery skips any skill whose name
appears in that set, preventing it from reappearing after a restart or folder
re-registration.

Also narrows `isManagedSkill` to only check the Kortex skills directory
(not all registered folders), so extension-registered skills are always
treated as external and correctly tracked as removed rather than deleted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Evzen Gasta <evzen.ml@seznam.cz>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 4, 2026

📝 Walkthrough

Walkthrough

This PR introduces tracking for removed/unregistered external skills to prevent their rediscovery. A new SKILL_REMOVED constant is added, and the SkillManager persists removed skill names to configuration, filters them during discovery, and updates unregister behavior for external skills.

Changes

Cohort / File(s) Summary
Skill Constants
packages/api/src/skill/skill-info.ts
Added exported constant SKILL_REMOVED with value 'removed' alongside existing skill configuration property constants.
Core Implementation
packages/main/src/plugin/skill/skill-manager.ts
Implemented removed skill tracking via removedNames Set; persisted to/loaded from config under SKILL_REMOVED; discovery filtering prevents rediscovery of removed external skills; simplified managed-skill detection logic to rely solely on directory comparison.
Test Suite
packages/main/src/plugin/skill/skill-manager.spec.ts
Refactored mockDirectoryWithSkills helper to accept baseDirectory parameter; updated existing tests for unregister behavior with removed semantics; added comprehensive test cases covering removal persistence, rediscovery prevention, external skill handling, and interaction with directory registration.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SkillManager
    participant Config
    participant Discovery

    User->>SkillManager: unregisterSkill('external-skill')
    Note over SkillManager: External skill detected
    SkillManager->>SkillManager: Add to removedNames Set
    SkillManager->>Config: saveSkillsToConfig()<br/>persist SKILL_REMOVED
    Config->>Config: Update config with removed names

    User->>SkillManager: init() / rediscoverSkills()
    SkillManager->>Discovery: processDiscoveredPaths()
    Discovery->>Discovery: Parse skill metadata
    Discovery->>SkillManager: Check removedNames Set
    alt Skill in removedNames
        SkillManager->>SkillManager: Skip skill
    else Skill not removed
        SkillManager->>SkillManager: Include skill
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: preventing removed external skills from being rediscovered on re-init, which is the core feature added across all modified files.
Description check ✅ Passed The description is directly related to the changeset, providing clear context about the SKILL_REMOVED config key, removedNames tracking, and the narrowed isManagedSkill logic that are all present in the actual code changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/main/src/plugin/skill/skill-manager.spec.ts (1)

719-721: Consider using regular string literals for simple YAML test data.

Static analysis flags these template literals as having no interpolation. While template literals work fine here, regular strings with explicit \n would be consistent with the static analysis rules. This is a minor stylistic preference.

Example fix for one instance
- [{ name: 'extra-skill', content: `---\nname: extra-skill\ndescription: An extra skill\n---\n# Extra\n` }],
+ [{ name: 'extra-skill', content: '---\nname: extra-skill\ndescription: An extra skill\n---\n# Extra\n' }],

Also applies to: 740-742, 802-804, 872-876, 964-966

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/main/src/plugin/skill/skill-manager.spec.ts` around lines 719 - 721,
Replace the template literals used for simple YAML test data with regular string
literals: change occurrences where objects like { name: 'extra-skill', content:
`---\nname: extra-skill\ndescription: An extra skill\n---\n# Extra\n` } (and the
similar literals at the other noted spots) to use plain quoted strings with
explicit \n sequences (e.g., '---\nname: extra-skill\n...') so static analysis
no longer flags them as unnecessary template literals; update each instance that
sets the content property in the test data (the objects passed alongside
EXTRA_DIR and similar test fixtures) to use regular string literals.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/main/src/plugin/skill/skill-manager.spec.ts`:
- Around line 719-721: Replace the template literals used for simple YAML test
data with regular string literals: change occurrences where objects like { name:
'extra-skill', content: `---\nname: extra-skill\ndescription: An extra
skill\n---\n# Extra\n` } (and the similar literals at the other noted spots) to
use plain quoted strings with explicit \n sequences (e.g., '---\nname:
extra-skill\n...') so static analysis no longer flags them as unnecessary
template literals; update each instance that sets the content property in the
test data (the objects passed alongside EXTRA_DIR and similar test fixtures) to
use regular string literals.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d892c35d-6677-44ad-b3e8-a471041e45fc

📥 Commits

Reviewing files that changed from the base of the PR and between 99316d9 and 4a51774.

📒 Files selected for processing (3)
  • packages/api/src/skill/skill-info.ts
  • packages/main/src/plugin/skill/skill-manager.spec.ts
  • packages/main/src/plugin/skill/skill-manager.ts

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant